home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1995 May / cd Ware (Juegos) Epimundo.iso / DOS / C / BETEDIT.ZIP / BETEDIT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-16  |  17.4 KB  |  515 lines

  1. /**************************************************************************
  2. *                                                                         *
  3. *   MODULE :  betedit.cpp                                                 *
  4. *                                                                         *
  5. *   Purpose:  Provides dialog controls derived from CEdit that validate   *
  6. *             the data entered with a minimum of help from the dialog     *
  7. *             containing the control.                                     *
  8. *                                                                         *
  9. *  Comments:  These classes were developed starting with the DATAVAL      *
  10. *             example code produced by Sara Williams of MicroSoft.        *
  11. *                                                                         *
  12. *   History:  Date      Reason                                            *
  13. *             --------  -----------------------------------               *
  14. *                                                                         *
  15. *             15/07/92  First version, provides CLongEdit and CRealEdit   *
  16. *                                                                         *
  17. **************************************************************************/
  18.  
  19.  
  20. #include <afxwin.h>                             // All the standard MFC stuff
  21. #include "betedit.h"
  22.  
  23. #pragma warning(disable: 4100)   // Disable "Unused formal parameter" warning
  24.  
  25.  
  26. /**************************************************************************
  27. *                                                                         *
  28. *   CLASS  :  CLongEdit                                                   *
  29. *                                                                         *
  30. *   Purpose:  Provides a dialog control for long values that validates    *
  31. *             the data entered with a minimum of help from the dialog     *
  32. *             containing the control.                                     *
  33. *                                                                         *
  34. *  Comments:                                                              *
  35. *                                                                         *
  36. *   History:  Date      Reason                                            *
  37. *             --------  -----------------------------------               *
  38. *                                                                         *
  39. *             15/07/92  Created                                           *
  40. *                                                                         *
  41. **************************************************************************/
  42.  
  43.  
  44. BEGIN_MESSAGE_MAP(CLongEdit, CEdit)
  45.     ON_WM_CHAR()
  46.     ON_WM_KILLFOCUS()
  47.     ON_MESSAGE(BEM_VALIDATE, OnValidate)
  48. END_MESSAGE_MAP()
  49.  
  50.  
  51. /////////////////////////////////////////////////////////////////////////////
  52. //
  53. // Constructor without parameters - set member variables to defaults
  54. //
  55. CLongEdit::CLongEdit()
  56. {
  57.     m_lValue = 0;
  58.     m_lMax = 100000;
  59.     m_lMin = -100000;
  60. }
  61.  
  62.  
  63. /////////////////////////////////////////////////////////////////////////////
  64. //
  65. // Destructor
  66. //
  67. CLongEdit::~CLongEdit()
  68. {
  69.     CEdit::~CEdit();          // Call base class destructor, but do nowt else
  70. }
  71.  
  72.  
  73. /////////////////////////////////////////////////////////////////////////////
  74. //
  75. // Creating from C++ code - Create Windows object to connect to C++ object,
  76. // set position, style etc.
  77. //
  78. BOOL CLongEdit::Create(DWORD dwStyle, const RECT& rect,
  79.         CWnd* pParentWnd, UINT nID)
  80. {
  81.     return CWnd::Create("EDIT", NULL, dwStyle, rect, pParentWnd, nID);
  82. }
  83.  
  84.  
  85. /////////////////////////////////////////////////////////////////////////////
  86. //
  87. // Aliasing on top of an existing Edit control
  88. //
  89. BOOL CLongEdit::SubclassEdit(UINT nID, CWnd* pParent, LONG lMin, LONG lMax)
  90. {
  91.     m_lMin = lMin;
  92.     m_lMax = lMax;
  93.     m_lValue = 0;
  94.     HWND hWndEdit = ::GetDlgItem(pParent->m_hWnd, nID);
  95.     if (hWndEdit == NULL)
  96.         return FALSE;
  97.     return SubclassWindow(hWndEdit);
  98. }
  99.  
  100.  
  101. /////////////////////////////////////////////////////////////////////////////
  102. //
  103. // Set up text to reflect current value - this member function is intended
  104. // to be used internally, but it might prove valuable ...
  105. //
  106. void CLongEdit::RefreshText()
  107. {
  108.     char    szBuf[20];
  109.  
  110.     wsprintf(szBuf, "%ld", m_lValue);
  111.     SetWindowText((LPSTR)szBuf);               // Set text to match the value
  112. }
  113.  
  114.  
  115. /////////////////////////////////////////////////////////////////////////////
  116. //
  117. // SetRange : set the allowed limits and recheck the value
  118. //
  119. BOOL CLongEdit::SetRange(LONG lMin, LONG lMax)
  120. {
  121.         m_lMin = lMin;                               // update the range info
  122.         m_lMax = lMax;
  123.         SetValue(m_lValue);           // This will check value against limits
  124.         return TRUE;
  125. }
  126.  
  127.  
  128. /////////////////////////////////////////////////////////////////////////////
  129. //
  130. // SetValue : Define current value after checks
  131. //
  132. void CLongEdit::SetValue(LONG lVal)
  133. {
  134.     if (lVal > m_lMax) lVal = m_lMax;            // Limit using allowed range
  135.     if (lVal < m_lMin) lVal = m_lMin;
  136.     m_lValue = lVal;
  137.     RefreshText();                                    // Get the text correct
  138. }
  139.  
  140.  
  141. /////////////////////////////////////////////////////////////////////////////
  142. //
  143. // GetValue : return current value
  144. //
  145. LONG CLongEdit::GetValue()
  146. {
  147.     Validate(FALSE);               // Ensure that current value is up to date
  148.     return m_lValue;
  149. }
  150.  
  151.  
  152. ////////////////////////////////////////////////////////////////////////////
  153. //
  154. // User defined message: check our value against range. If wParam is zero
  155. // the check is done silently, without error messages, otherwise an error
  156. // message is generated. lParam is not used.
  157. //
  158. afx_msg LONG CLongEdit::OnValidate(UINT uShow, LONG lParam)
  159. {
  160.     if (Validate((BOOL)uShow))
  161.         return 1;
  162.     else
  163.         return 0;
  164. }
  165.  
  166.  
  167. ////////////////////////////////////////////////////////////////////////////
  168. //
  169. // Test the data : check our value against range. If bShow is FALSE
  170. // the check is done silently, without error messages, otherwise an error
  171. // message is generated.
  172. //
  173. BOOL CLongEdit::Validate(BOOL bShow)
  174. {
  175.     char    szBuf[60];
  176.     char    szBuffer[60];
  177.     int     num;
  178.     LONG    lTry;
  179.  
  180.     num = GetLine(0, (LPSTR)szBuf, 55);           // Get our text in a string
  181.     szBuf[num] = 0;        // because GetLine does not insert null terminator
  182.     num = sscanf(szBuf, "%Fld", (LPLONG)&lTry);          // Get value as long
  183.     if (num >= 0)                                  // If conversion succeeded
  184.     {
  185.         if ((lTry >= m_lMin) && (lTry <= m_lMax))              // Check range
  186.         {                                    // Success, data can be accepted
  187.             m_lValue = lTry;                          // Update current value
  188.             RefreshText();                               // Get the text neat
  189.             return TRUE;                           // Return value sez all OK
  190.         }
  191.         else                                  // Here for number out of range
  192.         {
  193.             if (bShow)
  194.             {
  195.                 wsprintf(szBuffer, "Allowed range is %ld to %ld",
  196.                                    m_lMin, m_lMax);
  197.                 GetParent()->MessageBox(szBuffer,
  198.                              "Entry rejected - out of range", MB_OK);
  199.             }
  200.             return FALSE;                         // Return value for failure
  201.         }
  202.     }
  203.     else                              // Here for failed conversion to number
  204.     {
  205.         if (bShow)
  206.         {
  207.             wsprintf(szBuffer, "Numeric parseing failed %d", num);
  208.               GetParent()->MessageBox(szBuffer,
  209.                          "Entry rejected - bad data", MB_OK);
  210.         }
  211.         return FALSE;                             // Return value for failure
  212.     }
  213. }
  214.  
  215.  
  216. /////////////////////////////////////////////////////////////////////////////
  217. //
  218. // OnKillFocus : Test on loss of focus
  219. // If data invalid, post a message to the dialog box proc to cause error
  220. // message and restore the focus to this control. Don't forget to pass
  221. // the message on down to the base CEdit class or you're dead.
  222. //
  223. afx_msg void CLongEdit::OnKillFocus(CWnd* pWnd)
  224. {
  225.     if (!Validate(FALSE))                           // If the data is invalid
  226.         GetParent()->PostMessage(BEM_NOTVALID, GetDlgCtrlID(), 0);
  227.     CEdit::OnKillFocus(pWnd);          // Must pass this down to base class !
  228. }
  229.  
  230.  
  231. /////////////////////////////////////////////////////////////////////////////
  232. //
  233. // Input character filter
  234. // Throw away all non-numeric characters. We allow '0' to '9', '-' and < 0x20
  235. //
  236. afx_msg void CLongEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
  237. {
  238.     BOOL    bOk;
  239.  
  240.     bOk = ((nChar < 0x20) || ((nChar >= '0') && (nChar <= '9')) ||
  241.           (nChar == '-'));
  242.     if (bOk)
  243.     {
  244.         CEdit::OnChar(nChar, nRepCnt, nFlags);                   // permitted
  245.     }
  246.     else
  247.     {
  248.         OnBadInput();                    // illegal character - inform parent
  249.     }
  250. }
  251.  
  252.  
  253. /////////////////////////////////////////////////////////////////////////////
  254. //
  255. // default bad input handler, beep (unless parent notification
  256. // returns -1.  Most parent dialogs will return 0 or 1 for command
  257. // handlers (i.e. Beep is the default)
  258. //
  259. void CLongEdit::OnBadInput()
  260. {
  261.     if (GetParent()->SendMessage(WM_COMMAND,
  262.         GetDlgCtrlID(), MAKELONG(m_hWnd, BEN_ILLEGALCHAR)) != -1)
  263.     {
  264.         MessageBeep(-1);
  265.     }
  266. }
  267.  
  268.  
  269. /**************************************************************************
  270. *                                                                         *
  271. *   CLASS  :  CRealEdit                                                   *
  272. *                                                                         *
  273. *   Purpose:  Provides a dialog control for real values that validates    *
  274. *             the data entered with a minimum of help from the dialog     *
  275. *             containing the control.                                     *
  276. *                                                                         *
  277. *  Comments:                                                              *
  278. *                                                                         *
  279. *   History:  Date      Reason                                            *
  280. *             --------  -----------------------------------               *
  281. *                                                                         *
  282. *             15/07/92  Created                                           *
  283. *                                                                         *
  284. **************************************************************************/
  285.  
  286.  
  287. BEGIN_MESSAGE_MAP(CRealEdit, CEdit)
  288.     ON_WM_CHAR()
  289.     ON_WM_KILLFOCUS()
  290.     ON_MESSAGE(BEM_VALIDATE, OnValidate)
  291. END_MESSAGE_MAP()
  292.  
  293.  
  294. /////////////////////////////////////////////////////////////////////////////
  295. //
  296. // Constructor without parameters - set member variables to defaults
  297. //
  298. CRealEdit::CRealEdit()
  299. {
  300.     m_fValue = 0;
  301.     m_fMax = 100000;
  302.     m_fMin = -100000;
  303. }
  304.  
  305.  
  306. /////////////////////////////////////////////////////////////////////////////
  307. //
  308. // Destructor
  309. //
  310. CRealEdit::~CRealEdit()
  311. {
  312.     CEdit::~CEdit();          // Call base class destructor, but do nowt else
  313. }
  314.  
  315.  
  316. /////////////////////////////////////////////////////////////////////////////
  317. //
  318. // Creating from C++ code - Create Windows object to connect to C++ object,
  319. // set position, style etc.
  320. //
  321. BOOL CRealEdit::Create(DWORD dwStyle, const RECT& rect,
  322.         CWnd* pParentWnd, UINT nID)
  323. {
  324.     if (CWnd::Create("EDIT", NULL, dwStyle, rect, pParentWnd, nID))
  325.     {
  326.         return TRUE;
  327.     }
  328.     else
  329.         return FALSE;
  330. }
  331.  
  332.  
  333. /////////////////////////////////////////////////////////////////////////////
  334. //
  335. // Aliasing on top of an existing Edit control
  336. //
  337. BOOL CRealEdit::SubclassEdit(UINT nID, CWnd* pParent, float fMin, float fMax)
  338. {
  339.     m_fMin = fMin;
  340.     m_fMax = fMax;
  341.     m_fValue = 0;
  342.     HWND hWndEdit = ::GetDlgItem(pParent->m_hWnd, nID);
  343.     if (hWndEdit == NULL)
  344.         return FALSE;
  345.     return SubclassWindow(hWndEdit);
  346. }
  347.  
  348.  
  349. /////////////////////////////////////////////////////////////////////////////
  350. //
  351. // Set up text to reflect current value.
  352. //
  353. void CRealEdit::RefreshText()
  354. {
  355.     char    szBuf[20];
  356.  
  357.     sprintf(szBuf, "%g", m_fValue);
  358.     SetWindowText((LPSTR)szBuf);               // Set text to match the value
  359. }
  360.  
  361.  
  362. /////////////////////////////////////////////////////////////////////////////
  363. //
  364. // SetRange : set the allowed limits and recheck the value
  365. //
  366. BOOL CRealEdit::SetRange(float fMin, float fMax)
  367. {
  368.         m_fMin = fMin;                               // update the range info
  369.         m_fMax = fMax;
  370.         SetValue(m_fValue);           // This will check value against limits
  371.         return TRUE;
  372. }
  373.  
  374.  
  375. /////////////////////////////////////////////////////////////////////////////
  376. //
  377. // SetValue : Define current value after checks
  378. //
  379. void CRealEdit::SetValue(float fVal)
  380. {
  381.     if (fVal > m_fMax) fVal = m_fMax;            // Limit using allowed range
  382.     if (fVal < m_fMin) fVal = m_fMin;
  383.     m_fValue = fVal;
  384.     RefreshText();                                    // Get the text correct
  385. }
  386.  
  387.  
  388. /////////////////////////////////////////////////////////////////////////////
  389. //
  390. // GetValue : return current value
  391. //
  392. float CRealEdit::GetValue()
  393. {
  394.     Validate(FALSE);               // Ensure that current value is up to date
  395.     return m_fValue;
  396. }
  397.  
  398.  
  399. ////////////////////////////////////////////////////////////////////////////
  400. //
  401. // User defined message: check our value against range. If wParam is zero
  402. // the check is done silently, without error messages, otherwise an error
  403. // message is generated. lParam is not used.
  404. //
  405. afx_msg LONG CRealEdit::OnValidate(UINT uShow, LONG lParam)
  406. {
  407.     if (Validate((BOOL)uShow))
  408.         return 1;
  409.     else
  410.         return 0;
  411. }
  412.  
  413.  
  414. ////////////////////////////////////////////////////////////////////////////
  415. //
  416. // Test the data : check our value against range. If bShow is FALSE
  417. // the check is done silently, without error messages, otherwise an error
  418. // message is generated.
  419. //
  420. BOOL CRealEdit::Validate(BOOL bShow)
  421. {
  422.     char    szBuf[60];
  423.     char    szBuffer[60];
  424.     int     num;
  425.     float   fTry;
  426.  
  427.     num = GetLine(0, (LPSTR)szBuf, 55);           // Get our text in a string
  428.     szBuf[num] = 0;        // because GetLine does not insert null terminator
  429.     num = sscanf(szBuf, "%Ff", (float __far *)&fTry);   // Get value as float
  430.     if (num >= 0)                                  // If conversion succeeded
  431.     {
  432.         if ((fTry >= m_fMin) && (fTry <= m_fMax))              // Check range
  433.         {                                    // Success, data can be accepted
  434.             m_fValue = fTry;                          // Update current value
  435.             RefreshText();                               // Get the text neat
  436.             return TRUE;                           // Return value sez all OK
  437.         }
  438.         else                                  // Here for number out of range
  439.         {
  440.             if (bShow)
  441.             {
  442.                 sprintf(szBuffer, "Allowed range is %g to %g",
  443.                                    m_fMin, m_fMax);
  444.                 GetParent()->MessageBox(szBuffer,
  445.                              "Entry rejected - out of range", MB_OK);
  446.             }
  447.             return FALSE;                         // Return value for failure
  448.         }
  449.     }
  450.     else                              // Here for failed conversion to number
  451.     {
  452.         if (bShow)
  453.         {
  454.             wsprintf(szBuffer, "Numeric parseing failed %d", num);
  455.               GetParent()->MessageBox(szBuffer,
  456.                          "Entry rejected - bad data", MB_OK);
  457.         }
  458.         return FALSE;                             // Return value for failure
  459.     }
  460. }
  461.  
  462.  
  463. /////////////////////////////////////////////////////////////////////////////
  464. //
  465. // OnKillFocus : Test on loss of focus
  466. // If data invalid, post a message to the dialog box proc to cause error
  467. // message and restore the focus to this control. Don't forget to pass
  468. // the message on down to the base CEdit class or you're dead.
  469. //
  470. afx_msg void CRealEdit::OnKillFocus(CWnd* pWnd)
  471. {
  472.     if (!Validate(FALSE))                           // If the data is invalid
  473.         GetParent()->PostMessage(BEM_NOTVALID, GetDlgCtrlID(), 0);
  474.     CEdit::OnKillFocus(pWnd);          // Must pass this down to base class !
  475. }
  476.  
  477.  
  478. /////////////////////////////////////////////////////////////////////////////
  479. //
  480. // Input character filter
  481. // Throw away all non-float characters. We allow '0' to '9',
  482. // '-', '.', 'E' and < 0x20
  483. //
  484. afx_msg void CRealEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
  485. {
  486.     BOOL    bOk;
  487.  
  488.     bOk = ((nChar < 0x20) || ((nChar >= '0') && (nChar <= '9')) ||
  489.           (nChar == '-')  || (nChar == '.') || (nChar == 'E'));
  490.     if (bOk)
  491.     {
  492.         CEdit::OnChar(nChar, nRepCnt, nFlags);                   // permitted
  493.     }
  494.     else
  495.     {
  496.         OnBadInput();                    // illegal character - inform parent
  497.     }
  498. }
  499.  
  500.  
  501. /////////////////////////////////////////////////////////////////////////////
  502. //
  503. // default bad input handler, beep (unless parent notification
  504. // returns -1.  Most parent dialogs will return 0 or 1 for command
  505. // handlers (i.e. Beep is the default)
  506. //
  507. void CRealEdit::OnBadInput()
  508. {
  509.     if (GetParent()->SendMessage(WM_COMMAND,
  510.         GetDlgCtrlID(), MAKELONG(m_hWnd, BEN_ILLEGALCHAR)) != -1)
  511.     {
  512.         MessageBeep(-1);
  513.     }
  514. }
  515.